home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
- #
- # passwd.file.chk
- #
- # Check passsword file -- /etc/passswd -- for incorrect number of fields,
- # duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
- #
- # Awk part from _The AWK Programming Language_, page 78
- #
- # Mechanism: Passwd.check uses awk to ensure that each line of the file
- # has 7 fields, as well as examining the file for any duplicate users
- # by using "sort -u". It also checks to make sure that the password
- # field (the second one) is either a "*", meaning the group has no password,
- # or a non-null field (which would mean that the account has a null
- # password.) It then checks to ensure that all uids are alphanumeric,
- # and that all user id numbers are indeed numeric. For yellow pages
- # passwords, it does the same checking, but in order to get a listing of
- # all members of the password file, it does a "ypcat passwd > ./$$" and
- # uses that temporary file for a passfile. It removes the tmp file after
- # using it, of course.
- # The /etc/passwd file has a very specific format, making the task
- # fairly simple. Normally it has lines with 7 fields, each field
- # separated by a colon (:). The first field is the user id, the second
- # field is the encrypted password (an asterix (*) means the user id has no
- # password, otherwise the first two characters are the salt), the third
- # field is the user id number, the fourth field is the group id number,
- # the fifth field is the GECOS field (basically holds miscellaneous
- # information, varying from site to site), the sixth field is the home
- # directory of the user, and lastly the seventh field is the login shell
- # of the user. No blank lines should be present.
- # The SUN /etc/security/passwd.adjunct file also has a very specific
- # format, making the check task simple. Each entry has 7 fields, each field
- # separated by a colon (:). The first field is the user name which matches
- # the user name contained in the /etc/passwd file. The second field is the
- # encrypted password (an asterix (*) means the user login is disabled,
- # otherwise the first two characters are the salt). The password contained
- # in the /etc/passwd file is comprised of ##user_id where the user_id
- # matches the entry of the first field in both password files. The third
- # through fifth specify the minimum, maximum, and default security labels
- # for the user. The sixth and seventh fields specify which auditing flags
- # should be always or never monitored.
- # If a line begins with a plus sign (+), it is a yellow pages entry.
- # See passwd(5) for more information, if this applies to your site.
- #
-
- #
- # Parameters
- #
- passwd_file=$1
- passwd_adjunct_file=$2
- SUN_SECURITY=$3
-
- #
- # Utilities
- #
- AWK=/bin/awk
- DIFF=/usr/bin/diff
- ECHO=/bin/echo
- JOIN=/usr/bin/join
- RM=/bin/rm
- SORT=/usr/bin/sort
- TEST=/bin/test
- UNIQ=/usr/bin/uniq
-
- #
- # Important files:
- #
- join_passwd_1=./pwd$$.1.join
- join_passwd_2=./pwd$$.2.join
- sort_passwd=./pwd$$.sort
- sort_secure_passwd=./spwd$$.sort
-
- #
- # Testing the passwd file for problems
- #
- result=`$AWK -F: '{print $1}' $passwd_file | $SORT -t: | $UNIQ -d`
- if $TEST "$result"
- then
- $ECHO
- $ECHO "Warning! Duplicate uid(s) found in password file:"
- for USER in $result
- do
- $ECHO " $USER"
- done
- fi
-
- #
- # First line is for a yellow pages entry in the password file.
- # It really should check for correct yellow pages syntax....
- #
- $AWK 'BEGIN {FS = ":" } \
- {if (substr($1,1,1) != "+") { \
- if ($0 ~ /^[ ]*$/) { printf("\nWarning! Password file, line %d, is blank\n", NR) } else {
- if (NF != 7) {
- printf("\nWarning! Password file, line %d, does not have 7 fields: \n\t%s\n", NR, $0) } \
- if ($1 !~ /[A-Za-z0-9]/) {
- printf("\nWarning! Password file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0) } \
- if ($2 == "") {
- printf("\nWarning! Password file, line %d, no password: \n\t%s\n", NR, $0) } \
- if ("'$SUN_SECURITY'" == "TRUE" && "##"$1 != $2) {
- printf("\nWarning! Password file, line %d, invalid password field for SUN C2 Security: \n\t%s\n", NR, $0) } \
- if ($3 !~ /[0-9]/) {
- printf("\nWarning! Password file, line %d, nonnumeric user id: \n\t%s\n", NR, $0) } \
- if ($3 == "0" && $1 != "root") {
- printf("\nWarning! Password file, line %d, user %s has uid = 0 and is not root\n\t%s\n", NR, $1, $0) } \
- if ($4 !~ /[0-9]/) {
- printf("\nWarning! Password file, line %d, nonnumeric group id: \n\t%s\n", NR, $0) } \
- if ($6 !~ /^\//) {
- printf("\nWarning! Password file, line %d, invalid login directory: \n\t%s\n", NR, $0) } \
- }}}' $passwd_file
-
- #
- # Perform checks on the security enhanced version of SUNOS
- #
- if $TEST $SUN_SECURITY = "TRUE"
- then
- result=`$AWK -F: '{print $1}' $passwd_adjunct_file | $SORT -t: | $UNIQ -d`
- if $TEST "$result"
- then
- $ECHO
- $ECHO "Warning! Duplicate uid(s) found in password adjunct file:"
- for USER in $result
- do
- $ECHO " $USER"
- done
- fi
- #
- # Check that for each entry in the passwd file that there is a matching
- # entry in the passwd.adjunct file.
- #
- $SORT -t: -o $sort_passwd $passwd_file
- $SORT -t: -o $sort_secure_passwd $passwd_adjunct_file
- $JOIN -t: $sort_passwd $sort_secure_passwd > $join_passwd_1
- $JOIN -t: -a1 $sort_passwd $sort_secure_passwd > $join_passwd_2
- result=`$DIFF $join_passwd_1 $join_passwd_2`
- if $TEST "$result"
- then
- $ECHO
- $ECHO "Warning! Matching record(s) in password adjunct file not found for"
- $ECHO "these records in password file:"
- PREV=$$
- for USER in $result
- do
- if $TEST $PREV = ">"
- then
- $ECHO " $USER"
- fi
- PREV=$USER
- done
- fi
- #
- # Check that for each entry in the passwd.adjunct file that there is a
- # matching entry in the passwd file.
- #
- $RM -f $join_passwd_2
- $JOIN -t: -a2 $sort_passwd $sort_secure_passwd > $join_passwd_2
- result=`$DIFF $join_passwd_1 $join_passwd_2`
- if $TEST "$result"
- then
- $ECHO
- $ECHO "Warning! Matching record(s) in password file not found for"
- $ECHO "these records in password adjunct file"
- PREV=$$
- for USER in $result
- do
- if $TEST $PREV = ">"
- then
- $ECHO " $USER"
- fi
- PREV=$USER
- done
- fi
- #
- # Test the fields in the passwd.adjunct file for validity
- #
- $AWK 'BEGIN {FS = ":" } \
- {if (substr($1,1,1) != "+") { \
- if ($0 ~ /^[ ]*$/) { printf("\nWarning! Password adjunct file, line %d, is blank\n", NR) } else {
- if (NF != 7) {
- printf("\nWarning! Password adjunct file, line %d, does not have 7 fields: \n\t%s\n", NR, $0) } \
- if ($1 !~ /[A-Za-z0-9]/) {
- printf("\nWarning! Password adjunct file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0) } \
- if ($2 == "") {
- printf("\nWarning! Password adjunct file, line %d, no password: \n\t%s\n", NR, $0) } \
- #
- # Fields 3-5 are ignored since they deal with labels which are
- # currently unused on the SUN (perhaps a future B-level??)
- #
- # Fields 6+7 contain audit flags for the user and are selected
- # from the following: dr, dw, dc, da, lo, ad, p0, p1, and all.
- # More than 1 flag can be selected by separating flags with a
- # comma (,).
- #
- if ($6 != "") {
- j=1
- len=length($6)
- for (i=1; i<=len; i++) {
- if ((substr($6,i,1) != ",") && (i < len))
- continue
- if (i == len)
- token=substr($6,j,i-j+1)
- else
- token=substr($6,j,i-j)
- j=i+1
- if (token == "dr") continue
- if (token == "dw") continue
- if (token == "dc") continue
- if (token == "da") continue
- if (token == "lo") continue
- if (token == "ad") continue
- if (token == "p0") continue
- if (token == "p1") continue
- if (token == "all") continue
- printf("\nWarning! Password adjunct file, line %d, invalid audit flag: %s\n\t%s\n", NR, token, $0) } \
- }
- }}}' $passwd_adjunct_file
- fi
-
- #
- # Clean up after ourself
- #
- $RM -f $join_passwd_1
- $RM -f $join_passwd_2
- $RM -f $sort_passwd
- $RM -f $sort_secure_passwd
- # end
-